package com.ship.dispatch.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ship.common.core.base.Page;
import com.ship.common.core.domain.R;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.exception.ServiceException;
import com.ship.common.core.utils.FileUtils;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.common.log.annotation.Log;
import com.ship.common.log.enums.BusinessType;
import com.ship.common.security.utils.SecurityUtils;
import com.ship.dispatch.bean.*;
import com.ship.dispatch.bean.boats.CreateFreightAttachmentsRq;
import com.ship.dispatch.bean.boats.CreateFreightRq;
import com.ship.dispatch.bean.boats.info.QueryShipMessageInfo;
import com.ship.dispatch.bean.fob.SpFobFileRecord;
import com.ship.dispatch.bean.fob.SpFobJsfhccbItems;
import com.ship.dispatch.bpm.vo.dto.BGTableDto;
import com.ship.dispatch.service.*;
import com.ship.dispatch.service.fob.SpFobFileRecordService;
import com.ship.dispatch.service.fob.SpFobJsfhccbItemsService;
import com.ship.dispatch.util.UploadFreightUtil;
import com.ship.system.api.RemoteFileService;
import com.ship.system.api.domain.SysFile;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 船舶运费管理 前端控制器
 *
 * @author zhangyh
 * @since 2024-01-10
 */
@RestController
@RequestMapping("/ship/freight/cost")
@Api(value = "smShipFreightCost", tags = "船舶运费管理前端控制器")
public class SmShipFreightCostController {

    @Autowired
    private SmShipFreightCostService smShipFreightCostService;

    @Autowired
    private SpFobJsfhccbItemsService spFobJsfhccbItemsService;

    @Autowired
    private ExportService exportService;

    @Value("${freight_cost_template_url}")
    private String templateUrl;

    @Value("${freight_cost_add_template_url}")
    private String addTemplateUrl;

    @Value("${file_server.host}")
    private String fileServerHost;

    @Value("${freight_template_url}")
    private String freightTemplateUrl;

    @Autowired
    private RemoteFileService remoteFileService;

    @Autowired
    private SpInformationService spInformationService;

    @Autowired
    private UploadFreightUtil uploadFreightUtil;

    @Autowired
    SpFobFileRecordService spFobFileRecordService;

    @ApiOperation("查询船舶信息列表")
    @GetMapping("/query/shipMessage")
    public JsonResult queryShipMessage(@RequestParam(required = false) String queryType,@RequestParam(required = false) String queryValue){
        List<QueryShipMessageInfo> resultList = spInformationService.queryShipMessage(queryType,queryValue);
        return JsonResult.success(resultList);
    }

    @ApiOperation("新增船舶运费信息")
    @PostMapping("/add")
    public JsonResult addFreight(@RequestBody CreateFreightRq rq){
        boolean status = false;
        if (StringUtils.isNotEmpty(rq.getFileId())){
            SpFobFileRecord record = spFobFileRecordService.queryRecordById(rq.getFileId());
            if (null != record){
                status = smShipFreightCostService.addFreight(record,rq);
            }
        }else {
            status = smShipFreightCostService.addFreight(null,rq);
        }

        return JsonResult.success(status);
    }

    @ApiOperation("上传船舶运费附件")
    @PostMapping("/upload")
    public JsonResult uploadFile(@RequestParam("file") MultipartFile file) throws Exception {
        FileUtils.checkFileName(file);
        try {
            R<SysFile> result = remoteFileService.upload(file);
            if(result.getCode() != R.SUCCESS){
                throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
            }
            SpFobFileRecord spFobFileRecord = new SpFobFileRecord();
            spFobFileRecord.setPath(result.getData().getHttpsUrl());
            spFobFileRecord.setHttpPath(result.getData().getHttpUrl());
            spFobFileRecord.setName(file.getOriginalFilename());
            spFobFileRecord.setFileType("船舶运费");
            spFobFileRecord.setCreateDate(new Date());
            spFobFileRecord.setCreateBy(SecurityUtils.getStringUserId());
            spFobFileRecordService.save(spFobFileRecord);
            return JsonResult.success(spFobFileRecord.getId().toString());
        } catch (Exception e) {
            return JsonResult.failed("上传失败，原因：" + e.getMessage());
        }
    }

    @ApiOperation("根据运费ID保存相关附件信息")
    @PostMapping("/add/freightAttachments")
    public JsonResult addFreightAttachments(@RequestBody CreateFreightAttachmentsRq rq){
        if (StringUtils.isNotEmpty(rq.getFileId())){
            SpFobFileRecord record = spFobFileRecordService.queryRecordById(rq.getFileId());
            if (null != record){
                return smShipFreightCostService.addFreightAttachments(record,rq.getId());
            }
        }
        return JsonResult.failed("保存失败");
    }

    @ApiOperation("根据运费ID删除运费信息")
    @PostMapping("/delete/freight")
    public JsonResult deleteFreight(@RequestBody List<String> ids){
        boolean status = smShipFreightCostService.deleteFreight(ids);
        return JsonResult.success(status);
    }

    @ApiOperation("根据运费ID修改船舶运费信息")
    @PostMapping("/update/freightAttachments")
    public JsonResult updateFreightAttachmentsById(@RequestBody SpShipFreightAttachments rq){
        boolean status = smShipFreightCostService.updateFreightAttachmentsById(rq);
        return JsonResult.success(status);
    }

    /**
     * 船舶运费信息分页
     *
     * @param shipFreightCost
     * @return
     */
    @ApiOperation(value = "船舶运费信息分页")
    @PostMapping("/page")
    public JsonResult<Page<SmShipFreightCost>> basePage(@RequestBody SmShipFreightCost shipFreightCost) {
        Page<SmShipFreightCost> page = smShipFreightCostService.page(shipFreightCost,new QueryWrapper<>());
        return JsonResult.success(page);
    }

    /**
     * 船舶运费信息分页导出
     *
     * @return
     */
    @ApiOperation(value = "船舶运费信息分页导出")
    @PostMapping("/page/export")
    @Log(title = "船舶运费信息分页导出",businessType = BusinessType.EXPORT)
    public JsonResult pageExport(@RequestBody SmShipFreightCost shipFreightCost) {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        if(shipFreightCost.getIds() != null && shipFreightCost.getIds().size() > 0){
            queryWrapper.in("id",shipFreightCost.getIds());
        }
        List<SmShipFreightCost> exportList = smShipFreightCostService.pageExportList(shipFreightCost, queryWrapper,new LinkedList<>());
        if (CollectionUtil.isNotEmpty(exportList)){
            exportList.forEach(item -> {
                if (item.getVoyageStartTime() != null && item.getVoyageEndTime() != null) {
                    String startTime = cn.hutool.core.date.DateUtil.format(item.getVoyageStartTime(), DatePattern.NORM_DATETIME_FORMATTER);
                    String endTime = DateUtil.format(item.getVoyageEndTime(), DatePattern.NORM_DATETIME_FORMATTER);
                    String time = startTime + "-" + endTime;
                    item.setVoyageTime(time);
                }
            });
        }
        Field[] fields = SmShipFreightCost.class.getDeclaredFields();
        String url = exportService.pageExport(exportList,fields,exportService.listStrByModuleAndUser
                ("sm_ship_freight_cost", SecurityUtils.getUserId()), "船舶运费信息");
        return JsonResult.success(url);
    }

    /**
     * 获取船舶运费信息详情
     * @param costId
     * @return
     */
    @ApiOperation(value = "获取船舶运费信息详情")
    @GetMapping("/detail")
    public JsonResult getCostDetailInfo(@RequestParam Long costId,@RequestParam(required = false) String processInstanceId,@RequestParam(required = false) String key){
//        return spFobJsfhccbItemsService.getBgCostInfo(costId,processInstanceId,key);
        return smShipFreightCostService.queryRecordById(costId,processInstanceId,key);
    }

    @ApiOperation("根据详情ID上传附件信息")
    @PostMapping("/upload/freightAttachments")
    public JsonResult uploadFreightAttachments(@RequestBody CreateFreightAttachmentsRq rq){
        boolean status = smShipFreightCostService.updateFreightAttachmentsUrl(rq);
        return JsonResult.success(status);
    }




    /**
     * 船舶运费信息详情导出
     * @param costId
     * @return
     */
    @ApiOperation(value = "船舶运费信息详情导出")
    @GetMapping("/detail/export/{costId}/{processInstanceId}/{key}")
    public JsonResult exportCostDetailInfo(@PathVariable("costId") Long costId,@PathVariable("processInstanceId") String processInstanceId,@PathVariable("key") String key){
//        JsonResult jsonResult = spFobJsfhccbItemsService.getBgCostInfo(costId,processInstanceId,key);
        JsonResult jsonResult = smShipFreightCostService.queryRecordById(costId, processInstanceId, key);
        if(jsonResult.getResultCode() != 0){
            return jsonResult;
        }
        HashMap<String, Object> hashMap = (HashMap) jsonResult.getResultObject();
        JSONObject resultJson = new JSONObject(hashMap);
        String shipName = resultJson.getString("shipName");
        String time = resultJson.getString("time");
        JSONArray dataArray = resultJson.getJSONArray("data");
        if(dataArray == null || dataArray.size() == 0){
            return JsonResult.failed("暂无数据");
        }
        List<File> downloadFiles = new LinkedList<>();
        try{
            URL url = null;
            if (StringUtils.isNotEmpty(resultJson.getString("type")) && "1".equals(resultJson.getString("type"))){
                //获取运费模板
                url = new URL(addTemplateUrl);
            }else {
                //获取运费模板
                url = new URL(templateUrl);
            }
            InputStream inputStream = url.openStream();
            Workbook workbook = new XSSFWorkbook(inputStream);

            if (StringUtils.isNotEmpty(resultJson.getString("type")) && "1".equals(resultJson.getString("type"))){
                String voyageNumber = null;
                if (StringUtils.isNotEmpty(resultJson.getString("voyageNumber")) && "1".equals(resultJson.getString("voyageNumber"))){
                    voyageNumber = resultJson.getString("voyageNumber");
                }

                //替换头部
                replaceCostText(workbook,"VoyageNumber-VesselName-航次时间",null != voyageNumber ? voyageNumber + "-" : "" + shipName +"-"+"（"+time+"）");
            }else {
                //替换头部
                replaceCostText(workbook,"船舶名称（航次时间）",shipName+"（"+time+"）");
            }


            //创建临时压缩文件
            File zipFile = new File("船舶运费明细"+System.currentTimeMillis()+".zip");
            //替换内容
            for (Object data : dataArray) {
                BGTableDto dataTable = (BGTableDto)data;
                String tableName = dataTable.getTableName();
                List<SpFobJsfhccbItems> tableArray = dataTable.getTables();
                if(tableArray == null || tableArray.size() == 0){
                    continue;
                }
                for (SpFobJsfhccbItems table : tableArray) {
                    String headName = table.getA1();
                    replaceCostText(workbook,tableName+"-"+headName+"-a2",StringUtils.isNoneBlank(table.getA2()) ? table.getA2() : "");
                    replaceCostText(workbook,tableName+"-"+headName+"-a3",StringUtils.isNoneBlank(table.getA3()) ? table.getA3() : "");
                    replaceCostText(workbook,tableName+"-"+headName+"-a4",StringUtils.isNoneBlank(table.getA4()) ? table.getA4() : "");
                    replaceCostText(workbook,tableName+"-"+headName+"-a5",StringUtils.isNoneBlank(table.getA5()) ? table.getA5() : "");

                    //文件单独处理
                    if(StringUtils.isBlank(table.getA6())
                            || table.getFiels() == null || table.getFiels().size() == 0){
                        replaceCostText(workbook,tableName+"-"+headName+"-a6","");
                        continue;
                    }
                    SpFobFileRecord fileInfo = table.getFiels().get(0);
                    //文件下载进压缩包
                    String fileUrl = fileInfo.getPath();
                    String CsoldPart = "http://10.75.34.224:9300/statics";
                    String ZsoldPart = "http://10.75.33.149:9300/statics";
                    String CsPart = "https://lngshippingcs.cgp.cnooc/api/file/statics";
                    String ZsPart = "https://lngshipping.cgp.cnooc/api/file/statics";
                    String newUrl = "";
                    if (fileUrl.contains("https://lngshipping.cgp.cnooc")) {
                        newUrl = fileUrl.replace(ZsPart, ZsoldPart);
                    }else if (fileUrl.contains("https://lngshippingcs.cgp.cnooc")){
                        newUrl = fileUrl.replace(CsPart, CsoldPart);
                    }else {
                        newUrl = fileUrl;
                    }

                    URL otherUrl = new URL(newUrl);
                    InputStream otherInputStream = otherUrl.openStream();
                    String[] nameArr = fileInfo.getName().split("\\.");
                    File tempFile = File.createTempFile(nameArr[0], "."+nameArr[1]);
                    try (FileOutputStream fileOutputStream = new FileOutputStream(tempFile)) {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = otherInputStream.read(buffer)) != -1) {
                            fileOutputStream.write(buffer, 0, bytesRead);
                        }
                    }
                    downloadFiles.add(tempFile);
                    replaceCostText(workbook,tableName+"-"+headName+"-a6",tempFile.getName());
                }
            }

            File tempFile = File.createTempFile("船舶运费明细", ".xlsx");
            //创建输出流
            FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
            workbook.write(fileOutputStream);
            fileOutputStream.close();
            downloadFiles.add(tempFile);
            try (FileOutputStream fos = new FileOutputStream(zipFile);
                 ZipOutputStream zos = new ZipOutputStream(fos)) {
                for (File downloadFile : downloadFiles) {
                    ZipEntry zipEntry = new ZipEntry(downloadFile.getName());
                    zos.putNextEntry(zipEntry);
                    try (FileInputStream fis = new FileInputStream(downloadFile)) {
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = fis.read(buffer)) > 0) {
                            zos.write(buffer, 0, length);
                        }
                    }
                    zos.closeEntry();
                    downloadFile.delete();
                }
            }
            HashMap<String, Object> paramMap = new HashMap<>();
//            //文件
//            paramMap.put("file", zipFile);
//            //输出
//            paramMap.put("output","json");
//            //自定义路径
//            paramMap.put("path","zip");
//            //场景
//            paramMap.put("scene","zip");
//
//            paramMap.put("filename",zipFile.getName());

            FileInputStream input = new FileInputStream(zipFile);
            MultipartFile multipartFile = new MockMultipartFile("file", zipFile.getName(), "application/octet-stream", input);
            R<SysFile> result1 = remoteFileService.upload(multipartFile);
            if(result1.getCode() != R.SUCCESS){
                throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
            }
            String urls = result1.getData().getHttpsUrl();

            //上传
//            String result= HttpUtil.post(fileServerHost+"/group1/upload", paramMap);
//            Gson gson = new Gson();
//            JsonObject jsonObject = gson.fromJson(result, JsonObject.class);
            zipFile.delete();
            return JsonResult.success(urls);
        }catch (Exception e){
            e.printStackTrace();
            return JsonResult.failed("文件解析异常！");
        }
    }

    @ApiOperation("船舶运费模板下载")
    @GetMapping("/get/shipFreightTemple")
    public JsonResult getShipFreightTemple(){
        return JsonResult.success(freightTemplateUrl);
    }



    /**
     * 文本替换
     * @param workbook
     * @param oldText
     * @param newText
     */
    public void replaceCostText(Workbook workbook, String oldText, String newText){
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            Sheet sheet = workbook.getSheetAt(i);
            for (Row row : sheet) {
                for (Cell cell : row) {
                    if (cell.getCellType() == CellType.STRING && cell.getStringCellValue().equals(oldText)) {
                        cell.setCellValue(newText);
                    }
                }
            }
        }
    }
}
